<template>
  <canvas :canvas-id="canvasId" class="game-canvas"
    @touchstart="onTouchStart"
    @touchmove="onTouchMove"
    @touchend="onTouchEnd"
  ></canvas>
</template>

<script setup>
import { ref, onMounted, watch } from 'vue'
import { calcParabola, checkCollision } from '../utils/physics.js'

const props = defineProps({
  levelData: Object,
  width: {
    type: Number,
    default: 600
  },
  height: {
    type: Number,
    default: 400
  }
})

const emit = defineEmits(['success', 'fail', 'hitBalloon'])

const canvasId = ref('gameCanvas')
const ctx = ref(null)
const hammer = ref(null)
const balloons = ref([])
const obstacles = ref([])
const dragging = ref(false)
const dragStart = ref(null)
const velocity = ref({ x: 0, y: 0 })
const gravity = ref(0.5)
const animFrame = ref(null)
const gameOver = ref(false)

const initGame = () => {
  // 初始化canvas和关卡数据
  const query = uni.createSelectorQuery()
  query.select('.game-canvas').fields({ node: true, size: true }).exec(res => {
    ctx.value = uni.createCanvasContext(canvasId.value)
    resetLevel()
    draw()
  })
}

const resetLevel = () => {
  // 关卡数据初始化
  const { hammer: hammerData, balloons: balloonsData, obstacles: obstaclesData } = props.levelData || {}
  hammer.value = { ...hammerData, radius: 20, moving: false }
  balloons.value = (balloonsData || []).map(b => ({ ...b, radius: 18, broken: false }))
  obstacles.value = (obstaclesData || []).map(o => ({ ...o, radius: 22 }))
  gameOver.value = false
}

const onTouchStart = (e) => {
  if (hammer.value.moving || gameOver.value) return
  const touch = e.touches[0]
  const dx = touch.x - hammer.value.x
  const dy = touch.y - hammer.value.y
  if (Math.sqrt(dx*dx + dy*dy) < hammer.value.radius + 10) {
    dragging.value = true
    dragStart.value = { x: touch.x, y: touch.y }
  }
}

const onTouchMove = (e) => {
  if (!dragging.value) return
  // 可视化拉动方向
}

const onTouchEnd = (e) => {
  if (!dragging.value) return
  const touch = e.changedTouches[0]
  // 计算发射速度（反方向）
  const vx = (dragStart.value.x - touch.x) / 8
  const vy = (dragStart.value.y - touch.y) / 8
  velocity.value = { x: vx, y: vy }
  hammer.value.moving = true
  dragging.value = false
  animate()
}

const animate = () => {
  if (!hammer.value.moving || gameOver.value) return
  // 更新锤子位置
  hammer.value.x += velocity.value.x
  hammer.value.y += velocity.value.y
  velocity.value.y += gravity.value
  // 边界检测
  if (hammer.value.x < 0 || hammer.value.x > props.width || hammer.value.y > props.height) {
    hammer.value.moving = false
    gameOver.value = true
    emit('fail')
    return
  }
  // 气球碰撞
  for (let b of balloons.value) {
    if (!b.broken && checkCollision(hammer.value, b)) {
      b.broken = true
      emit('hitBalloon', b)
      // 检查是否所有气球都被击中
      if (balloons.value.every(balloon => balloon.broken)) {
        gameOver.value = true
        emit('success')
        return
      }
    }
  }
  // 障碍物碰撞
  for (let o of obstacles.value) {
    if (checkCollision(hammer.value, o)) {
      hammer.value.moving = false
      gameOver.value = true
      emit('fail')
      return
    }
  }
  draw()
  animFrame.value = requestAnimationFrame(animate)
}

const draw = () => {
  if (!ctx.value) return
  // 清空画布
  ctx.value.clearRect(0, 0, props.width, props.height)
  // 绘制锤子
  ctx.value.beginPath()
  ctx.value.arc(hammer.value.x, hammer.value.y, hammer.value.radius, 0, 2 * Math.PI)
  ctx.value.fillStyle = '#007aff'
  ctx.value.fill()
  // 绘制气球
  for (let b of balloons.value) {
    if (!b.broken) {
      ctx.value.beginPath()
      ctx.value.arc(b.x, b.y, b.radius, 0, 2 * Math.PI)
      ctx.value.fillStyle = '#ff6b6b'
      ctx.value.fill()
    }
  }
  // 绘制障碍物
  for (let o of obstacles.value) {
    ctx.value.beginPath()
    ctx.value.arc(o.x, o.y, o.radius, 0, 2 * Math.PI)
    ctx.value.fillStyle = '#666'
    ctx.value.fill()
  }
  ctx.value.draw()
}

// 监听levelData变化
watch(() => props.levelData, () => {
  resetLevel()
}, { deep: true })

onMounted(() => {
  initGame()
})
</script>

<style scoped>
.game-canvas {
  width: 100%;
  height: 100%;
  background-color: #f8f8f8;
}
</style> 